home *** CD-ROM | disk | FTP | other *** search
- /* Expand the basic unary and binary arithmetic operations, for GNU compiler.
- Copyright (C) 1987, 1988 Free Software Foundation, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- #include "config.h"
- #include "rtl.h"
- #include "tree.h"
- #include "flags.h"
- #include "insn-flags.h"
- #include "insn-codes.h"
- #include "expr.h"
- #include "insn-config.h"
- #include "recog.h"
-
- /* In ANSI C we could write MODE + 1, but traditional C compilers
- seem to reject it. */
- #define INC_MODE(MODE) (enum machine_mode) ((int)(MODE) + 1)
-
- /* Each optab contains info on how this target machine
- can perform a particular operation
- for all sizes and kinds of operands.
-
- The operation to be performed is often specified
- by passing one of these optabs as an argument.
-
- See expr.h for documentation of these optabs. */
-
- optab add_optab;
- optab sub_optab;
- optab smul_optab;
- optab umul_optab;
- optab smul_widen_optab;
- optab umul_widen_optab;
- optab sdiv_optab;
- optab sdivmod_optab;
- optab udiv_optab;
- optab udivmod_optab;
- optab smod_optab;
- optab umod_optab;
- optab flodiv_optab;
- optab ftrunc_optab;
- optab and_optab;
- optab andcb_optab;
- optab ior_optab;
- optab xor_optab;
- optab ashl_optab;
- optab lshr_optab;
- optab lshl_optab;
- optab ashr_optab;
- optab rotl_optab;
- optab rotr_optab;
-
- optab mov_optab;
- optab movstrict_optab;
-
- optab neg_optab;
- optab abs_optab;
- optab one_cmpl_optab;
- optab ffs_optab;
-
- optab cmp_optab;
- optab ucmp_optab; /* Used only for libcalls for unsigned comparisons. */
- optab tst_optab;
-
- /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
- gives the gen_function to make a branch to test that condition. */
-
- rtxfun bcc_gen_fctn[NUM_RTX_CODE];
-
- /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
- gives the gen_function to make a store-condition insn
- to test that condition. */
-
- rtxfun setcc_gen_fctn[NUM_RTX_CODE];
-
- /* Generate code to perform an operation specified by BINOPTAB
- on operands OP0 and OP1, with result having machine-mode MODE.
-
- UNSIGNEDP is for the case where we have to widen the operands
- to perform the operation. It says to use zero-extension.
-
- If TARGET is nonzero, the value
- is generated there, if it is convenient to do so.
- In all cases an rtx is returned for the locus of the value;
- this may or may not be TARGET. */
-
- rtx
- expand_binop (mode, binoptab, op0, op1, target, unsignedp, methods)
- enum machine_mode mode;
- optab binoptab;
- rtx op0, op1;
- rtx target;
- int unsignedp;
- enum optab_methods methods;
- {
- enum mode_class class;
- enum machine_mode wider_mode;
- register rtx temp;
- rtx last;
-
- class = GET_MODE_CLASS (mode);
-
- op0 = protect_from_queue (op0, 0);
- op1 = protect_from_queue (op1, 0);
- if (target)
- target = protect_from_queue (target, 1);
-
- #if 0
- /* We may get better code by generating the result in a register
- when the target is not one of the operands. */
- if (target && ! rtx_equal_p (target, op1) && ! rtx_equal_p (target, op0))
- target_is_not_an_operand = 1;
- #endif
-
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
-
- /* Record where to delete back to if we backtrack. */
- last = get_last_insn ();
-
- /* If operation is commutative,
- try to make the first operand a register.
- Even better, try to make it the same as the target.
- Also try to make the last operand a constant. */
- if (binoptab == add_optab
- || binoptab == and_optab
- || binoptab == ior_optab
- || binoptab == xor_optab
- || binoptab == smul_optab
- || binoptab == umul_optab
- || binoptab == smul_widen_optab
- || binoptab == umul_widen_optab)
- {
- if (((target == 0 || GET_CODE (target) == REG)
- ? ((GET_CODE (op1) == REG
- && GET_CODE (op0) != REG)
- || target == op1)
- : rtx_equal_p (op1, target))
- ||
- GET_CODE (op0) == CONST_INT)
- {
- temp = op1;
- op1 = op0;
- op0 = temp;
- }
- }
-
- /* If we can do it with a three-operand insn, do so. */
-
- if (methods != OPTAB_MUST_WIDEN
- && binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) binoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- enum machine_mode mode1 = insn_operand_mode[icode][2];
- rtx pat;
- rtx xop0 = op0, xop1 = op1;
-
- if (target)
- temp = target;
- else
- temp = gen_reg_rtx (mode);
-
- /* In case the insn wants input operands in modes different from
- the result, convert the operands. */
-
- if (GET_MODE (op0) != VOIDmode
- && GET_MODE (op0) != mode0)
- xop0 = convert_to_mode (mode0, xop0, unsignedp);
-
- if (GET_MODE (xop1) != VOIDmode
- && GET_MODE (xop1) != mode1)
- xop1 = convert_to_mode (mode1, xop1, unsignedp);
-
- /* Now, if insn requires register operands, put operands into regs. */
-
- if (! (*insn_operand_predicate[icode][1]) (xop0, mode0))
- xop0 = force_reg (mode0, xop0);
-
- if (! (*insn_operand_predicate[icode][2]) (xop1, mode1))
- xop1 = force_reg (mode1, xop1);
-
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
- temp = gen_reg_rtx (mode);
-
- pat = GEN_FCN (icode) (temp, xop0, xop1);
- if (pat)
- {
- emit_insn (pat);
- return temp;
- }
- else
- delete_insns_since (last);
- }
-
- /* It can't be open-coded in this mode.
- Use a library call if one is available and caller says that's ok. */
-
- if (binoptab->handlers[(int) mode].lib_call
- && (methods == OPTAB_LIB || methods == OPTAB_LIB_WIDEN))
- {
- rtx insn_before, insn_first, insn_last;
- rtx funexp = gen_rtx (SYMBOL_REF, Pmode,
- binoptab->handlers[(int) mode].lib_call);
-
- /* Pass the address through a pseudoreg, if desired,
- before the "beginning" of the library call.
- So this insn isn't "part of" the library call, in case that
- is deleted, or cse'd. */
- #ifndef NO_FUNCTION_CSE
- if (! flag_no_function_cse)
- funexp = copy_to_mode_reg (Pmode, funexp);
- #endif
-
- insn_before = get_last_insn ();
- if (insn_before == 0)
- abort ();
-
- /* Cannot pass FUNEXP since emit_library_call insists
- on getting a SYMBOL_REF. But cse will make this SYMBOL_REF
- be replaced with the copy we made just above. */
- /* Pass 1 for NO_QUEUE so we don't lose any increments
- if the libcall is cse'd or moved. */
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
- binoptab->handlers[(int) mode].lib_call),
- 1, mode, 2, op0, mode, op1, mode);
- target = hard_libcall_value (mode);
- temp = copy_to_reg (target);
-
- insn_first = NEXT_INSN (insn_before);
- insn_last = get_last_insn ();
-
- REG_NOTES (insn_last)
- = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (binoptab->code, mode, op0, op1),
- gen_rtx (INSN_LIST, REG_RETVAL, insn_first,
- REG_NOTES (insn_last)));
- REG_NOTES (insn_first)
- = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
- REG_NOTES (insn_first));
- return temp;
- }
-
- delete_insns_since (last);
-
- /* It can't be done in this mode. Can we do it in a wider mode? */
-
- if (! (methods == OPTAB_WIDEN || methods == OPTAB_LIB_WIDEN
- || methods == OPTAB_MUST_WIDEN))
- return 0; /* Caller says, don't even try. */
-
- /* Compute the value of METHODS to pass to recursive calls.
- Don't allow widening to be tried recursively. */
-
- methods = (methods == OPTAB_LIB_WIDEN ? OPTAB_LIB : OPTAB_DIRECT);
-
- /* Widening is now independent of specific machine modes.
- It is assumed that widening may be performed to any
- higher numbered mode in the same mode class. */
-
- if (class == MODE_INT || class == MODE_FLOAT)
- {
- for (wider_mode = INC_MODE (mode);
- ((int) wider_mode < (int) MAX_MACHINE_MODE
- && GET_MODE_CLASS (wider_mode) == class);
- wider_mode = INC_MODE (wider_mode))
- {
- if ((binoptab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- || (methods == OPTAB_LIB
- && binoptab->handlers[(int) wider_mode].lib_call))
- {
- rtx xop0 = op0, xop1 = op1;
- int no_extend = 0;
-
- /* For certain operations, we need not actually extend
- the narrow operands, as long as we will truncate
- the results to the same narrowness. */
-
- if (binoptab == ior_optab || binoptab == and_optab
- || binoptab == xor_optab || binoptab == andcb_optab
- || binoptab == add_optab || binoptab == sub_optab
- || binoptab == smul_optab || binoptab == umul_optab
- || binoptab == ashl_optab || binoptab == lshl_optab)
- no_extend = 1;
-
- if (GET_MODE (xop0) != VOIDmode)
- {
- if (no_extend)
- {
- temp = force_reg (GET_MODE (xop0), xop0);
- xop0 = gen_rtx (SUBREG, wider_mode, temp, 0);
- }
- else
- {
- temp = gen_reg_rtx (wider_mode);
- convert_move (temp, xop0, unsignedp);
- xop0 = temp;
- }
- }
- if (GET_MODE (xop1) != VOIDmode)
- {
- if (no_extend)
- {
- temp = force_reg (GET_MODE (xop1), xop1);
- xop1 = gen_rtx (SUBREG, wider_mode, temp, 0);
- }
- else
- {
- temp = gen_reg_rtx (wider_mode);
- convert_move (temp, xop1, unsignedp);
- xop1 = temp;
- }
- }
-
- temp = expand_binop (wider_mode, binoptab, xop0, xop1, 0,
- unsignedp, methods);
- if (temp)
- {
- if (class == MODE_FLOAT)
- {
- if (target == 0)
- target = gen_reg_rtx (mode);
- convert_move (target, temp, 0);
- return target;
- }
- else
- return gen_lowpart (mode, temp);
- }
- else
- delete_insns_since (last);
- }
- }
- }
-
- return 0;
- }
-
- /* Expand a binary operator which has both signed and unsigned forms.
- UOPTAB is the optab for unsigned operations, and SOPTAB is for
- signed operations.
-
- If we widen unsigned operands, we may use a signed wider operation instead
- of an unsigned wider operation, since the result would be the same. */
-
- rtx
- sign_expand_binop (mode, uoptab, soptab, op0, op1, target, unsignedp, methods)
- enum machine_mode mode;
- optab uoptab, soptab;
- rtx op0, op1, target;
- int unsignedp;
- enum optab_methods methods;
- {
- register rtx temp;
- optab direct_optab = unsignedp ? uoptab : soptab;
- struct optab wide_soptab;
-
- /* Do it without widening, if possible. */
- temp = expand_binop (mode, direct_optab, op0, op1, target,
- unsignedp, OPTAB_DIRECT);
- if (temp || methods == OPTAB_DIRECT)
- return temp;
-
- /* Try widening to a signed int. Make a fake signed optab that
- hides any signed insn for direct use. */
- wide_soptab = *soptab;
- wide_soptab.handlers[(int) mode].insn_code = CODE_FOR_nothing;
- wide_soptab.handlers[(int) mode].lib_call = 0;
-
- temp = expand_binop (mode, &wide_soptab, op0, op1, target,
- unsignedp, OPTAB_WIDEN);
-
- /* For unsigned operands, try widening to an unsigned int. */
- if (temp == 0 && unsignedp)
- temp = expand_binop (mode, uoptab, op0, op1, target,
- unsignedp, OPTAB_WIDEN);
- if (temp || methods == OPTAB_WIDEN)
- return temp;
-
- /* Use the right width lib call if that exists. */
- temp = expand_binop (mode, direct_optab, op0, op1, target, unsignedp, OPTAB_LIB);
- if (temp || methods == OPTAB_LIB)
- return temp;
-
- /* Must widen and use a lib call, use either signed or unsigned. */
- temp = expand_binop (mode, &wide_soptab, op0, op1, target,
- unsignedp, methods);
- if (temp != 0)
- return temp;
- if (unsignedp)
- return expand_binop (mode, uoptab, op0, op1, target,
- unsignedp, methods);
- return 0;
- }
-
- /* Generate code to perform an operation specified by BINOPTAB
- on operands OP0 and OP1, with two results to TARG1 and TARG2.
- We assume that the order of the operands for the instruction
- is TARG0, OP0, OP1, TARG1, which would fit a pattern like
- [(set TARG0 (operate OP0 OP1)) (set TARG1 (operate ...))].
-
- Either TARG0 or TARG1 may be zero, but what that means is that
- that result is not actually wanted. We will generate it into
- a dummy pseudo-reg and discard it. They may not both be zero.
-
- Returns 1 if this operation can be performed; 0 if not. */
-
- int
- expand_twoval_binop (binoptab, op0, op1, targ0, targ1, unsignedp)
- optab binoptab;
- rtx op0, op1;
- rtx targ0, targ1;
- int unsignedp;
- {
- enum machine_mode mode = GET_MODE (targ0 ? targ0 : targ1);
- enum mode_class class;
- enum machine_mode wider_mode;
-
- class = GET_MODE_CLASS (mode);
-
- op0 = protect_from_queue (op0, 0);
- op1 = protect_from_queue (op1, 0);
-
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- op1 = force_not_mem (op1);
- }
-
- if (targ0)
- targ0 = protect_from_queue (targ0, 1);
- else
- targ0 = gen_reg_rtx (mode);
- if (targ1)
- targ1 = protect_from_queue (targ1, 1);
- else
- targ1 = gen_reg_rtx (mode);
-
- if (binoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- emit_insn (GEN_FCN (binoptab->handlers[(int) mode].insn_code)
- (targ0, op0, op1, targ1));
- return 1;
- }
-
- /* It can't be done in this mode. Can we do it in a wider mode? */
-
- if (class == MODE_INT || class == MODE_FLOAT)
- {
- for (wider_mode = INC_MODE (mode);
- ((int) wider_mode < (int) MAX_MACHINE_MODE
- && GET_MODE_CLASS (wider_mode) == class);
- wider_mode = INC_MODE (wider_mode))
- {
- if (binoptab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- {
- expand_twoval_binop_convert (binoptab, wider_mode, op0, op1,
- targ0, targ1, unsignedp);
- return 1;
- }
- }
- }
- return 0;
- }
-
- int
- expand_twoval_binop_convert (binoptab, mode, op0, op1, targ0, targ1, unsignedp)
- register optab binoptab;
- register rtx op0, op1, targ0, targ1;
- int unsignedp;
- {
- register rtx t0 = gen_reg_rtx (SImode);
- register rtx t1 = gen_reg_rtx (SImode);
- register rtx temp;
-
- temp = gen_reg_rtx (SImode);
- convert_move (temp, op0, unsignedp);
- op0 = temp;
- temp = gen_reg_rtx (SImode);
- convert_move (temp, op1, unsignedp);
- op1 = temp;
-
- expand_twoval_binop (binoptab, op0, op1, t0, t1, unsignedp);
- convert_move (targ0, t0, unsignedp);
- convert_move (targ1, t1, unsignedp);
- return 1;
- }
-
- /* Generate code to perform an operation specified by UNOPTAB
- on operand OP0, with result having machine-mode MODE.
-
- UNSIGNEDP is for the case where we have to widen the operands
- to perform the operation. It says to use zero-extension.
-
- If TARGET is nonzero, the value
- is generated there, if it is convenient to do so.
- In all cases an rtx is returned for the locus of the value;
- this may or may not be TARGET. */
-
- rtx
- expand_unop (mode, unoptab, op0, target, unsignedp)
- enum machine_mode mode;
- optab unoptab;
- rtx op0;
- rtx target;
- int unsignedp;
- {
- enum mode_class class;
- enum machine_mode wider_mode;
- register rtx temp;
-
- class = GET_MODE_CLASS (mode);
-
- op0 = protect_from_queue (op0, 0);
-
- if (flag_force_mem)
- {
- op0 = force_not_mem (op0);
- }
-
- if (target)
- target = protect_from_queue (target, 1);
-
- if (unoptab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) unoptab->handlers[(int) mode].insn_code;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
-
- if (target)
- temp = target;
- else
- temp = gen_reg_rtx (mode);
-
- if (GET_MODE (op0) != VOIDmode
- && GET_MODE (op0) != mode0)
- op0 = convert_to_mode (mode0, op0, unsignedp);
-
- /* Now, if insn requires register operands, put operands into regs. */
-
- if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
- op0 = force_reg (mode0, op0);
-
- if (! (*insn_operand_predicate[icode][0]) (temp, mode))
- temp = gen_reg_rtx (mode);
-
- emit_insn (GEN_FCN (icode) (temp, op0));
- return temp;
- }
- else if (unoptab->handlers[(int) mode].lib_call)
- {
- rtx insn_before, insn_last;
- rtx funexp = gen_rtx (SYMBOL_REF, Pmode,
- unoptab->handlers[(int) mode].lib_call);
-
- /* Pass the address through a pseudoreg, if desired,
- before the "beginning" of the library call (for deletion). */
- #ifndef NO_FUNCTION_CSE
- if (! flag_no_function_cse)
- funexp = copy_to_mode_reg (Pmode, funexp);
- #endif
-
- insn_before = get_last_insn ();
-
- /* Cannot pass FUNEXP since emit_library_call insists
- on getting a SYMBOL_REF. But cse will make this SYMBOL_REF
- be replaced with the copy we made just above. */
- /* Pass 1 for NO_QUEUE so we don't lose any increments
- if the libcall is cse'd or moved. */
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
- unoptab->handlers[(int) mode].lib_call),
- 1, mode, 1, op0, mode);
- target = hard_libcall_value (mode);
- temp = copy_to_reg (target);
- insn_last = get_last_insn ();
- REG_NOTES (insn_last)
- = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (unoptab->code, mode, op0),
- gen_rtx (INSN_LIST, REG_RETVAL,
- NEXT_INSN (insn_before),
- REG_NOTES (insn_last)));
- REG_NOTES (NEXT_INSN (insn_before))
- = gen_rtx (INSN_LIST, REG_LIBCALL, insn_last,
- REG_NOTES (NEXT_INSN (insn_before)));
- return temp;
- }
-
- /* It can't be done in this mode. Can we do it in a wider mode? */
-
- if (class == MODE_INT || class == MODE_FLOAT)
- {
- for (wider_mode = INC_MODE (mode);
- ((int) wider_mode < (int) MAX_MACHINE_MODE
- && GET_MODE_CLASS (wider_mode) == class);
- wider_mode = INC_MODE (wider_mode))
- {
- if ((unoptab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- || unoptab->handlers[(int) wider_mode].lib_call)
- {
- if (GET_MODE (op0) != VOIDmode)
- {
- temp = gen_reg_rtx (wider_mode);
- convert_move (temp, op0, unsignedp);
- op0 = temp;
- }
-
- target = expand_unop (wider_mode, unoptab, op0, 0, unsignedp);
- if (class == MODE_FLOAT)
- {
- if (target == 0)
- target = gen_reg_rtx (mode);
- convert_move (target, temp, 0);
- return target;
- }
- else
- return gen_lowpart (mode, target);
- }
- }
- }
-
- return 0;
- }
-
- /* Generate an instruction whose insn-code is INSN_CODE,
- with two operands: an output TARGET and an input OP0.
- TARGET *must* be nonzero, and the output is always stored there.
- CODE is an rtx code such that (CODE OP0) is an rtx that describes
- the value that is stored into TARGET. */
-
- void
- emit_unop_insn (icode, target, op0, code)
- int icode;
- rtx target;
- rtx op0;
- enum rtx_code code;
- {
- register rtx temp;
- enum machine_mode mode0 = insn_operand_mode[icode][1];
- rtx insn;
- rtx prev_insn;
-
- temp = target = protect_from_queue (target, 1);
-
- op0 = protect_from_queue (op0, 0);
-
- if (flag_force_mem)
- op0 = force_not_mem (op0);
-
- /* Now, if insn requires register operands, put operands into regs. */
-
- if (! (*insn_operand_predicate[icode][1]) (op0, mode0))
- op0 = force_reg (mode0, op0);
-
- if (! (*insn_operand_predicate[icode][0]) (temp, GET_MODE (temp))
- || (flag_force_mem && GET_CODE (temp) == MEM))
- temp = gen_reg_rtx (GET_MODE (temp));
-
- prev_insn = get_last_insn ();
- insn = emit_insn (GEN_FCN (icode) (temp, op0));
-
- /* If we just made a multi-insn sequence,
- record in the last insn an equivalent expression for its value
- and a pointer to the first insn. This makes cse possible. */
- if (code != UNKNOWN && PREV_INSN (insn) != prev_insn)
- REG_NOTES (insn)
- = gen_rtx (EXPR_LIST, REG_EQUAL,
- gen_rtx (code, GET_MODE (temp), op0),
- REG_NOTES (insn));
-
- if (temp != target)
- emit_move_insn (target, temp);
- }
-
- /* Generate code to store zero in X. */
-
- void
- emit_clr_insn (x)
- rtx x;
- {
- emit_move_insn (x, const0_rtx);
- }
-
- /* Generate code to store 1 in X
- assuming it contains zero beforehand. */
-
- void
- emit_0_to_1_insn (x)
- rtx x;
- {
- emit_move_insn (x, const1_rtx);
- }
-
- /* Generate code to compare X with Y
- so that the condition codes are set.
-
- UNSIGNEDP nonzero says that X and Y are unsigned;
- this matters if they need to be widened.
-
- If they have mode BLKmode, then SIZE specifies the size of both X and Y,
- and ALIGN specifies the known shared alignment of X and Y. */
-
- void
- emit_cmp_insn (x, y, size, unsignedp, align)
- rtx x, y;
- rtx size;
- int unsignedp;
- int align;
- {
- enum machine_mode mode = GET_MODE (x);
- enum mode_class class;
- enum machine_mode wider_mode;
-
- if (mode == VOIDmode) mode = GET_MODE (y);
- /* They could both be VOIDmode if both args are immediate constants,
- but we should fold that at an earlier stage.
- With no special code here, this will call abort,
- reminding the programmer to implement such folding. */
-
- class = GET_MODE_CLASS (mode);
-
- if (mode != BLKmode && flag_force_mem)
- {
- x = force_not_mem (x);
- y = force_not_mem (y);
- }
-
- /* Handle all BLKmode compares. */
-
- if (mode == BLKmode)
- {
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- if (size == 0)
- abort ();
- #ifdef HAVE_cmpstrqi
- if (HAVE_cmpstrqi
- && GET_CODE (size) == CONST_INT
- && INTVAL (size) < (1 << GET_MODE_BITSIZE (QImode)))
- emit_insn (gen_cmpstrqi (x, y, size,
- gen_rtx (CONST_INT, VOIDmode, align)));
- else
- #endif
- #ifdef HAVE_cmpstrhi
- if (HAVE_cmpstrhi
- && GET_CODE (size) == CONST_INT
- && INTVAL (size) < (1 << GET_MODE_BITSIZE (HImode)))
- emit_insn (gen_cmpstrhi (x, y, size,
- gen_rtx (CONST_INT, VOIDmode, align)));
- else
- #endif
- #ifdef HAVE_cmpstrsi
- if (HAVE_cmpstrsi)
- emit_insn (gen_cmpstrsi (x, y, convert_to_mode (SImode, size, 1),
- gen_rtx (CONST_INT, VOIDmode, align)));
- else
- #endif
- {
- #ifdef TARGET_MEM_FUNCTIONS
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "memcmp"), 0,
- SImode, 3,
- XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
- #else
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "bcmp"), 0,
- SImode, 3,
- XEXP (x, 0), Pmode, XEXP (y, 0), Pmode,
- size, Pmode);
- #endif
- emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0);
- }
- return;
- }
-
- /* Handle some compares against zero. */
-
- if (y == CONST0_RTX (mode)
- && tst_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) tst_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn requires register operands, put operands into regs. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = force_reg (insn_operand_mode[icode][0], x);
-
- emit_insn (GEN_FCN (icode) (x));
- return;
- }
-
- /* Handle compares for which there is a directly suitable insn. */
-
- if (cmp_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing)
- {
- int icode = (int) cmp_optab->handlers[(int) mode].insn_code;
-
- emit_queue ();
- x = protect_from_queue (x, 0);
- y = protect_from_queue (y, 0);
-
- /* Now, if insn requires register operands, put operands into regs. */
- if (! (*insn_operand_predicate[icode][0])
- (x, insn_operand_mode[icode][0]))
- x = force_reg (insn_operand_mode[icode][0], x);
-
- if (! (*insn_operand_predicate[icode][1])
- (y, insn_operand_mode[icode][1]))
- y = force_reg (insn_operand_mode[icode][1], y);
-
- emit_insn (GEN_FCN (icode) (x, y));
- return;
- }
-
- /* Try widening if we can find a direct insn that way. */
-
- if (class == MODE_INT || class == MODE_FLOAT)
- {
- for (wider_mode = INC_MODE (mode);
- ((int) wider_mode < (int) MAX_MACHINE_MODE
- && GET_MODE_CLASS (wider_mode) == class);
- wider_mode = INC_MODE (wider_mode))
- {
- if (cmp_optab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- {
- x = convert_to_mode (wider_mode, x, unsignedp);
- y = convert_to_mode (wider_mode, y, unsignedp);
- emit_cmp_insn (x, y, 0, unsignedp, align);
- return;
- }
- }
- }
-
- /* Handle a lib call just for the mode we are using. */
-
- if (cmp_optab->handlers[(int) mode].lib_call)
- {
- char *string = cmp_optab->handlers[(int) mode].lib_call;
- /* If we want unsigned, and this mode has a distinct unsigned
- comparison routine, use that. */
- if (unsignedp && ucmp_optab->handlers[(int) mode].lib_call)
- string = ucmp_optab->handlers[(int) mode].lib_call;
-
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, string), 0,
- SImode, 2, x, mode, y, mode);
-
- /* Integer comparison returns a result that must be compared against 1,
- so that even if we do an unsigned compare afterward,
- there is still a value that can represent the result "less than". */
- if (GET_MODE_CLASS (mode) == MODE_INT)
- emit_cmp_insn (hard_libcall_value (SImode), const1_rtx, 0, unsignedp, 0);
- else
- emit_cmp_insn (hard_libcall_value (SImode), const0_rtx, 0, 0, 0);
- return;
- }
-
- /* Try widening and then using a libcall. */
-
- if (class == MODE_FLOAT)
- {
- for (wider_mode = INC_MODE (mode);
- ((int) wider_mode < (int) MAX_MACHINE_MODE
- && GET_MODE_CLASS (wider_mode) == class);
- wider_mode = INC_MODE (wider_mode))
- {
- if ((cmp_optab->handlers[(int) wider_mode].insn_code
- != CODE_FOR_nothing)
- || (cmp_optab->handlers[(int) wider_mode].lib_call != 0))
- {
- x = convert_to_mode (wider_mode, x, unsignedp);
- y = convert_to_mode (wider_mode, y, unsignedp);
- emit_cmp_insn (x, y, 0, unsignedp, align);
- }
- }
- return;
- }
-
- abort ();
- }
-
- /* These three functions generate an insn body and return it
- rather than emitting the insn.
-
- They do not protect from queued increments,
- because they may be used 1) in protect_from_queue itself
- and 2) in other passes where there is no queue. */
-
- /* Generate and return an insn body to add Y to X. */
-
- rtx
- gen_add2_insn (x, y)
- rtx x, y;
- {
- return (GEN_FCN (add_optab->handlers[(int) GET_MODE (x)].insn_code)
- (x, x, y));
- }
-
- int
- have_add2_insn (mode)
- enum machine_mode mode;
- {
- return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
- }
-
- /* Generate and return an insn body to subtract Y from X. */
-
- rtx
- gen_sub2_insn (x, y)
- rtx x, y;
- {
- return (GEN_FCN (sub_optab->handlers[(int) GET_MODE (x)].insn_code)
- (x, x, y));
- }
-
- int
- have_sub2_insn (mode)
- enum machine_mode mode;
- {
- return add_optab->handlers[(int) mode].insn_code != CODE_FOR_nothing;
- }
-
- /* Generate the body of an instruction to copy Y into X. */
-
- rtx
- gen_move_insn (x, y)
- rtx x, y;
- {
- register enum machine_mode mode = GET_MODE (x);
- if (mode == VOIDmode)
- mode = GET_MODE (y);
- return (GEN_FCN (mov_optab->handlers[(int) mode].insn_code) (x, y));
- }
-
- #if 0
- /* Tables of patterns for extending one integer mode to another. */
- enum insn_code zero_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];
- enum insn_code sign_extend_optab[MAX_MACHINE_MODE][MAX_MACHINE_MODE];
-
- /* Generate the body of an insn to extend Y (with mode MFROM)
- into X (with mode MTO). Do zero-extension if UNSIGNEDP is nonzero. */
-
- rtx
- gen_extend_insn (x, y, mto, mfrom, unsignedp)
- rtx x, y;
- enum machine_mode mto, mfrom;
- int unsignedp;
- {
- return (GEN_FCN ((unsignedp ? zero_extend_optab : sign_extend_optab)
- [(int)mto][(int)mfrom])
- (x, y));
- }
-
- static void
- init_extends ()
- {
- bzero (sign_extend_optab, sizeof sign_extend_optab);
- bzero (zero_extend_optab, sizeof zero_extend_optab);
- sign_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_extendhisi2;
- sign_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_extendqisi2;
- sign_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_extendqihi2;
- zero_extend_optab[(int) SImode][(int) HImode] = CODE_FOR_zero_extendhisi2;
- zero_extend_optab[(int) SImode][(int) QImode] = CODE_FOR_zero_extendqisi2;
- zero_extend_optab[(int) HImode][(int) QImode] = CODE_FOR_zero_extendqihi2;
- }
- #endif
-
- /* can_fix_p and can_float_p say whether the target machine
- can directly convert a given fixed point type to
- a given floating point type, or vice versa.
- The returned value is the CODE_FOR_... value to use,
- or CODE_FOR_nothing if these modes cannot be directly converted. */
-
- static enum insn_code fixtab[2][2][2];
- static enum insn_code fixtrunctab[2][2][2];
- static enum insn_code floattab[2][2];
-
- /* *TRUNCP_PTR is set to 1 if it is necessary to output
- an explicit FTRUNC insn before the fix insn; otherwise 0. */
-
- static enum insn_code
- can_fix_p (fixmode, fltmode, unsignedp, truncp_ptr)
- enum machine_mode fltmode, fixmode;
- int unsignedp;
- int *truncp_ptr;
- {
- *truncp_ptr = 0;
- if (fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp]
- != CODE_FOR_nothing)
- return fixtrunctab[fltmode != SFmode][fixmode == DImode][unsignedp];
- if (ftrunc_optab->handlers[(int) fltmode].insn_code != CODE_FOR_nothing)
- {
- *truncp_ptr = 1;
- return fixtab[fltmode != SFmode][fixmode == DImode][unsignedp];
- }
- return CODE_FOR_nothing;
- }
-
- static enum insn_code
- can_float_p (fltmode, fixmode)
- enum machine_mode fixmode, fltmode;
- {
- return floattab[fltmode != SFmode][fixmode == DImode];
- }
-
- void
- init_fixtab ()
- {
- enum insn_code *p;
- for (p = fixtab[0][0];
- p < fixtab[0][0] + sizeof fixtab / sizeof (fixtab[0][0][0]);
- p++)
- *p = CODE_FOR_nothing;
- for (p = fixtrunctab[0][0];
- p < fixtrunctab[0][0] + sizeof fixtrunctab / sizeof (fixtrunctab[0][0][0]);
- p++)
- *p = CODE_FOR_nothing;
-
- #ifdef HAVE_fixsfsi2
- if (HAVE_fixsfsi2)
- fixtab[0][0][0] = CODE_FOR_fixsfsi2;
- #endif
- #ifdef HAVE_fixsfdi2
- if (HAVE_fixsfdi2)
- fixtab[0][1][0] = CODE_FOR_fixsfdi2;
- #endif
- #ifdef HAVE_fixdfsi2
- if (HAVE_fixdfsi2)
- fixtab[1][0][0] = CODE_FOR_fixdfsi2;
- #endif
- #ifdef HAVE_fixdfdi2
- if (HAVE_fixdfdi2)
- fixtab[1][1][0] = CODE_FOR_fixdfdi2;
- #endif
-
- #ifdef HAVE_fixunssfsi2
- if (HAVE_fixunssfsi2)
- fixtab[0][0][1] = CODE_FOR_fixunssfsi2;
- #endif
- #ifdef HAVE_fixunssfdi2
- if (HAVE_fixunssfdi2)
- fixtab[0][1][1] = CODE_FOR_fixunssfdi2;
- #endif
- #ifdef HAVE_fixunsdfsi2
- if (HAVE_fixunsdfsi2)
- fixtab[1][0][1] = CODE_FOR_fixunsdfsi2;
- #endif
- #ifdef HAVE_fixunsdfdi2
- if (HAVE_fixunsdfdi2)
- fixtab[1][1][1] = CODE_FOR_fixunsdfdi2;
- #endif
-
- #ifdef HAVE_fix_truncsfsi2
- if (HAVE_fix_truncsfsi2)
- fixtrunctab[0][0][0] = CODE_FOR_fix_truncsfsi2;
- #endif
- #ifdef HAVE_fix_truncsfdi2
- if (HAVE_fix_truncsfdi2)
- fixtrunctab[0][1][0] = CODE_FOR_fix_truncsfdi2;
- #endif
- #ifdef HAVE_fix_truncdfsi2
- if (HAVE_fix_truncdfsi2)
- fixtrunctab[1][0][0] = CODE_FOR_fix_truncdfsi2;
- #endif
- #ifdef HAVE_fix_truncdfdi2
- if (HAVE_fix_truncdfdi2)
- fixtrunctab[1][1][0] = CODE_FOR_fix_truncdfdi2;
- #endif
-
- #ifdef HAVE_fixuns_truncsfsi2
- if (HAVE_fixuns_truncsfsi2)
- fixtrunctab[0][0][1] = CODE_FOR_fixuns_truncsfsi2;
- #endif
- #ifdef HAVE_fixuns_truncsfdi2
- if (HAVE_fixuns_truncsfdi2)
- fixtrunctab[0][1][1] = CODE_FOR_fixuns_truncsfdi2;
- #endif
- #ifdef HAVE_fixuns_truncdfsi2
- if (HAVE_fixuns_truncdfsi2)
- fixtrunctab[1][0][1] = CODE_FOR_fixuns_truncdfsi2;
- #endif
- #ifdef HAVE_fixuns_truncdfdi2
- if (HAVE_fixuns_truncdfdi2)
- fixtrunctab[1][1][1] = CODE_FOR_fixuns_truncdfdi2;
- #endif
-
- #ifdef FIXUNS_TRUNC_LIKE_FIX_TRUNC
- /* This flag says the same insns that convert to a signed fixnum
- also convert validly to an unsigned one. */
- {
- int i;
- int j;
- for (i = 0; i < 2; i++)
- for (j = 0; j < 2; j++)
- fixtrunctab[i][j][1] = fixtrunctab[i][j][0];
- }
- #endif
- }
-
- void
- init_floattab ()
- {
- enum insn_code *p;
- for (p = floattab[0];
- p < floattab[0] + sizeof floattab / sizeof (floattab[0][0]);
- p++)
- *p = CODE_FOR_nothing;
-
- #ifdef HAVE_floatsisf2
- if (HAVE_floatsisf2)
- floattab[0][0] = CODE_FOR_floatsisf2;
- #endif
- #ifdef HAVE_floatdisf2
- if (HAVE_floatdisf2)
- floattab[0][1] = CODE_FOR_floatdisf2;
- #endif
- #ifdef HAVE_floatsidf2
- if (HAVE_floatsidf2)
- floattab[1][0] = CODE_FOR_floatsidf2;
- #endif
- #ifdef HAVE_floatdidf2
- if (HAVE_floatdidf2)
- floattab[1][1] = CODE_FOR_floatdidf2;
- #endif
- }
-
- /* Generate code to convert FROM to floating point
- and store in TO. FROM must be fixed point.
- UNSIGNEDP nonzero means regard FROM as unsigned.
- Normally this is done by correcting the final value
- if it is negative. */
-
- void
- expand_float (real_to, from, unsignedp)
- rtx real_to, from;
- int unsignedp;
- {
- enum insn_code icode;
- register rtx to;
-
- /* Constants should get converted in `fold'.
- We lose here since we don't know the mode. */
- if (GET_MODE (from) == VOIDmode)
- abort ();
-
- to = real_to = protect_from_queue (real_to, 1);
- from = protect_from_queue (from, 0);
-
- if (flag_force_mem)
- {
- from = force_not_mem (from);
- }
-
- /* If we are about to do some arithmetic to correct for an
- unsigned operand, do it in a register. */
-
- if (unsignedp && GET_CODE (to) != REG)
- to = gen_reg_rtx (GET_MODE (to));
-
- /* Now do the basic conversion. Do it in the specified modes if possible;
- otherwise convert either input, output or both with wider mode;
- otherwise use a library call. */
-
- if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))
- != CODE_FOR_nothing)
- {
- emit_unop_insn (icode, to, from, FLOAT);
- }
- else if (GET_MODE (to) == SFmode
- && ((icode = can_float_p (DFmode, GET_MODE (from)))
- != CODE_FOR_nothing))
- {
- to = gen_reg_rtx (DFmode);
- emit_unop_insn (icode, to, from, FLOAT);
- }
- /* If we can't float a SI, maybe we can float a DI.
- If so, convert to DI and then float. */
- else if (GET_MODE (from) != DImode
- && (can_float_p (GET_MODE (to), DImode) != CODE_FOR_nothing
- || can_float_p (DFmode, DImode) != CODE_FOR_nothing))
- {
- register rtx tem = gen_reg_rtx (DImode);
- convert_move (tem, from, unsignedp);
- from = tem;
- /* If we extend FROM then we don't need to correct
- the final value for unsignedness. */
- unsignedp = 0;
-
- if ((icode = can_float_p (GET_MODE (to), GET_MODE (from)))
- != CODE_FOR_nothing)
- {
- emit_unop_insn (icode, to, from, FLOAT);
- }
- else if ((icode = can_float_p (DFmode, DImode))
- != CODE_FOR_nothing)
- {
- to = gen_reg_rtx (DFmode);
- emit_unop_insn (icode, to, from, FLOAT);
- }
- }
- /* No hardware instruction available; call a library
- to convert from SImode or DImode into DFmode. */
- else
- {
- if (GET_MODE_SIZE (GET_MODE (from)) < GET_MODE_SIZE (SImode))
- {
- from = convert_to_mode (SImode, from, unsignedp);
- unsignedp = 0;
- }
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
- (GET_MODE (from) == SImode ? "__floatsidf"
- : "__floatdidf")),
- 0, DFmode, 1, from, GET_MODE (from));
- to = copy_to_reg (hard_libcall_value (DFmode));
- }
-
- /* If FROM was unsigned but we treated it as signed,
- then in the case where it is negative (and therefore TO is negative),
- correct its value by 2**bitwidth. */
-
- if (unsignedp)
- {
- rtx label = gen_label_rtx ();
- rtx temp;
- REAL_VALUE_TYPE offset;
-
- do_pending_stack_adjust ();
- emit_cmp_insn (to, GET_MODE (to) == DFmode ? dconst0_rtx : fconst0_rtx,
- 0, 0, 0);
- emit_jump_insn (gen_bge (label));
- offset = REAL_VALUE_LDEXP (1.0, GET_MODE_BITSIZE (GET_MODE (from)));
- temp = expand_binop (GET_MODE (to), add_optab, to,
- immed_real_const_1 (offset, GET_MODE (to)),
- to, 0, OPTAB_LIB_WIDEN);
- if (temp != to)
- emit_move_insn (to, temp);
- do_pending_stack_adjust ();
- emit_label (label);
- }
-
- /* Copy result to requested destination
- if we have been computing in a temp location. */
-
- if (to != real_to)
- {
- if (GET_MODE (real_to) == GET_MODE (to))
- emit_move_insn (real_to, to);
- else
- convert_move (real_to, to, 0);
- }
- }
-
- /* expand_fix: generate code to convert FROM to fixed point
- and store in TO. FROM must be floating point. */
-
- static rtx
- ftruncify (x)
- rtx x;
- {
- rtx temp = gen_reg_rtx (GET_MODE (x));
- return expand_unop (GET_MODE (x), ftrunc_optab, x, temp, 0);
- }
-
- void
- expand_fix (to, from, unsignedp)
- register rtx to, from;
- int unsignedp;
- {
- enum insn_code icode;
- register rtx target;
- int must_trunc = 0;
-
- while (1)
- {
- icode = can_fix_p (GET_MODE (to), GET_MODE (from), unsignedp, &must_trunc);
- if (icode != CODE_FOR_nothing)
- {
- if (must_trunc)
- from = ftruncify (from);
-
- emit_unop_insn (icode, to, from, FIX);
- return;
- }
-
- #if 0 /* Turned off. It fails because the positive numbers
- that become temporarily negative are rounded up instead of down. */
-
- /* If no insns for unsigned conversion,
- we can go via a signed number.
- But make sure we won't overflow in the compiler. */
- if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_INT
- /* Make sure we won't lose significant bits doing this. */
- && GET_MODE_BITSIZE (GET_MODE (from)) > GET_MODE_BITSIZE (GET_MODE (to)))
- {
- icode = can_fix_p (GET_MODE (to), GET_MODE (from),
- 0, &must_trunc);
-
- if (icode != CODE_FOR_nothing)
- {
- REAL_VALUE_TYPE offset;
- rtx temp, temp1;
- int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
-
- if (must_trunc)
- from = ftruncify (from);
-
- /* Subtract 2**(N-1), convert to signed number,
- then add 2**(N-1). */
- offset = REAL_VALUE_LDEXP (1.0, bitsize - 1);
- temp = expand_binop (GET_MODE (from), sub_optab, from,
- immed_real_const_1 (offset, GET_MODE (from)),
- 0, 0, OPTAB_LIB_WIDEN);
-
- temp1 = gen_reg_rtx (GET_MODE (to));
- emit_unop_insn (icode, temp1, temp, FIX);
- temp = expand_binop (GET_MODE (to), add_optab, temp1,
- gen_rtx (CONST_INT, VOIDmode,
- 1 << (bitsize - 1)),
- to, 1, OPTAB_LIB_WIDEN);
- if (temp != to)
- emit_move_insn (to, temp);
- return;
- }
- }
- #endif
- icode = can_fix_p (DImode, GET_MODE (from), unsignedp, &must_trunc);
-
- if (GET_MODE (to) != DImode && icode != CODE_FOR_nothing)
- {
- register rtx temp = gen_reg_rtx (DImode);
-
- if (must_trunc)
- from = ftruncify (from);
- emit_unop_insn (icode, temp, from, FIX);
- convert_move (to, temp, unsignedp);
- return;
- }
-
- /* If FROM is not DFmode, convert to DFmode and try again from there. */
- if (GET_MODE (from) == DFmode)
- break;
-
- from = convert_to_mode (DFmode, from, 0);
- }
-
- /* We can't do it with an insn, so use a library call.
- The mode of FROM is known to be DFmode. */
-
- to = protect_from_queue (to, 1);
- from = protect_from_queue (from, 0);
-
- if (flag_force_mem)
- from = force_not_mem (from);
-
- if (GET_MODE (to) != DImode)
- {
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
- unsignedp ? "__fixunsdfsi"
- : "__fixdfsi"),
- 0, SImode, 1, from, DFmode);
- target = hard_libcall_value (SImode);
- }
- else
- {
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode,
- unsignedp ? "__fixunsdfdi"
- : "__fixdfdi"),
- 0, DImode, 1, from, DFmode);
- target = hard_libcall_value (DImode);
- }
-
- if (GET_MODE (to) == GET_MODE (target))
- emit_move_insn (to, target);
- else
- convert_move (to, target, 0);
- }
-
- static optab
- init_optab (code)
- enum rtx_code code;
- {
- int i;
- optab op = (optab) malloc (sizeof (struct optab));
- op->code = code;
- for (i = 0; i < NUM_MACHINE_MODES; i++)
- {
- op->handlers[i].insn_code = CODE_FOR_nothing;
- op->handlers[i].lib_call = 0;
- }
- return op;
- }
-
- /* Call this once to initialize the contents of the optabs
- appropriately for the current target machine. */
-
- void
- init_optabs ()
- {
- init_fixtab ();
- init_floattab ();
- init_comparisons ();
- /* init_extends (); */
-
- add_optab = init_optab (PLUS);
- sub_optab = init_optab (MINUS);
- smul_optab = init_optab (MULT);
- umul_optab = init_optab (UMULT);
- smul_widen_optab = init_optab (MULT);
- umul_widen_optab = init_optab (UMULT);
- sdiv_optab = init_optab (DIV);
- sdivmod_optab = init_optab (UNKNOWN);
- udiv_optab = init_optab (UDIV);
- udivmod_optab = init_optab (UNKNOWN);
- smod_optab = init_optab (MOD);
- umod_optab = init_optab (UMOD);
- flodiv_optab = init_optab (DIV);
- ftrunc_optab = init_optab (UNKNOWN);
- and_optab = init_optab (AND);
- andcb_optab = init_optab (UNKNOWN);
- ior_optab = init_optab (IOR);
- xor_optab = init_optab (XOR);
- ashl_optab = init_optab (ASHIFT);
- ashr_optab = init_optab (ASHIFTRT);
- lshl_optab = init_optab (LSHIFT);
- lshr_optab = init_optab (LSHIFTRT);
- rotl_optab = init_optab (ROTATE);
- rotr_optab = init_optab (ROTATERT);
- mov_optab = init_optab (UNKNOWN);
- movstrict_optab = init_optab (UNKNOWN);
- cmp_optab = init_optab (UNKNOWN);
- ucmp_optab = init_optab (UNKNOWN);
- tst_optab = init_optab (UNKNOWN);
- neg_optab = init_optab (NEG);
- abs_optab = init_optab (ABS);
- one_cmpl_optab = init_optab (NOT);
- ffs_optab = init_optab (FFS);
-
- #ifdef HAVE_addqi3
- if (HAVE_addqi3)
- add_optab->handlers[(int) QImode].insn_code = CODE_FOR_addqi3;
- #endif
- #ifdef HAVE_addhi3
- if (HAVE_addhi3)
- add_optab->handlers[(int) HImode].insn_code = CODE_FOR_addhi3;
- #endif
- #ifdef HAVE_addsi3
- if (HAVE_addsi3)
- add_optab->handlers[(int) SImode].insn_code = CODE_FOR_addsi3;
- #endif
- #ifdef HAVE_adddi3
- if (HAVE_adddi3)
- add_optab->handlers[(int) DImode].insn_code = CODE_FOR_adddi3;
- #endif
- #ifdef HAVE_addsf3
- if (HAVE_addsf3)
- add_optab->handlers[(int) SFmode].insn_code = CODE_FOR_addsf3;
- #endif
- #ifdef HAVE_adddf3
- if (HAVE_adddf3)
- add_optab->handlers[(int) DFmode].insn_code = CODE_FOR_adddf3;
- #endif
- add_optab->handlers[(int) DImode].lib_call = "__adddi3";
- add_optab->handlers[(int) SFmode].lib_call = "__addsf3";
- add_optab->handlers[(int) DFmode].lib_call = "__adddf3";
-
- #ifdef HAVE_subqi3
- if (HAVE_subqi3)
- sub_optab->handlers[(int) QImode].insn_code = CODE_FOR_subqi3;
- #endif
- #ifdef HAVE_subhi3
- if (HAVE_subhi3)
- sub_optab->handlers[(int) HImode].insn_code = CODE_FOR_subhi3;
- #endif
- #ifdef HAVE_subsi3
- if (HAVE_subsi3)
- sub_optab->handlers[(int) SImode].insn_code = CODE_FOR_subsi3;
- #endif
- #ifdef HAVE_subdi3
- if (HAVE_subdi3)
- sub_optab->handlers[(int) DImode].insn_code = CODE_FOR_subdi3;
- #endif
- #ifdef HAVE_subsf3
- if (HAVE_subsf3)
- sub_optab->handlers[(int) SFmode].insn_code = CODE_FOR_subsf3;
- #endif
- #ifdef HAVE_subdf3
- if (HAVE_subdf3)
- sub_optab->handlers[(int) DFmode].insn_code = CODE_FOR_subdf3;
- #endif
- sub_optab->handlers[(int) DImode].lib_call = "__subdi3";
- sub_optab->handlers[(int) SFmode].lib_call = "__subsf3";
- sub_optab->handlers[(int) DFmode].lib_call = "__subdf3";
-
- #ifdef HAVE_mulqi3
- if (HAVE_mulqi3)
- smul_optab->handlers[(int) QImode].insn_code = CODE_FOR_mulqi3;
- #endif
- #ifdef HAVE_mulhi3
- if (HAVE_mulhi3)
- smul_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulhi3;
- #endif
- #ifdef HAVE_mulsi3
- if (HAVE_mulsi3)
- smul_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulsi3;
- #endif
- #ifdef HAVE_muldi3
- if (HAVE_muldi3)
- smul_optab->handlers[(int) DImode].insn_code = CODE_FOR_muldi3;
- #endif
- #ifdef HAVE_mulsf3
- if (HAVE_mulsf3)
- smul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_mulsf3;
- #endif
- #ifdef HAVE_muldf3
- if (HAVE_muldf3)
- smul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_muldf3;
- #endif
-
- #ifdef MULSI3_LIBCALL
- smul_optab->handlers[(int) SImode].lib_call = MULSI3_LIBCALL;
- #else
- smul_optab->handlers[(int) SImode].lib_call = "__mulsi3";
- #endif
- smul_optab->handlers[(int) DImode].lib_call = "__muldi3";
- smul_optab->handlers[(int) SFmode].lib_call = "__mulsf3";
- smul_optab->handlers[(int) DFmode].lib_call = "__muldf3";
-
- #ifdef HAVE_mulqihi3
- if (HAVE_mulqihi3)
- smul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_mulqihi3;
- #endif
- #ifdef HAVE_mulhisi3
- if (HAVE_mulhisi3)
- smul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_mulhisi3;
- #endif
- #ifdef HAVE_mulsidi3
- if (HAVE_mulsidi3)
- smul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_mulsidi3;
- #endif
-
- #ifdef HAVE_umulqi3
- if (HAVE_umulqi3)
- umul_optab->handlers[(int) QImode].insn_code = CODE_FOR_umulqi3;
- #endif
- #ifdef HAVE_umulhi3
- if (HAVE_umulhi3)
- umul_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulhi3;
- #endif
- #ifdef HAVE_umulsi3
- if (HAVE_umulsi3)
- umul_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulsi3;
- #endif
- #ifdef HAVE_umuldi3
- if (HAVE_umuldi3)
- umul_optab->handlers[(int) DImode].insn_code = CODE_FOR_umuldi3;
- #endif
- #ifdef HAVE_umulsf3
- if (HAVE_umulsf3)
- umul_optab->handlers[(int) SFmode].insn_code = CODE_FOR_umulsf3;
- #endif
- #ifdef HAVE_umuldf3
- if (HAVE_umuldf3)
- umul_optab->handlers[(int) DFmode].insn_code = CODE_FOR_umuldf3;
- #endif
-
- #ifdef UMULSI3_LIBCALL
- umul_optab->handlers[(int) SImode].lib_call = UMULSI3_LIBCALL;
- #else
- umul_optab->handlers[(int) SImode].lib_call = "__umulsi3";
- #endif
- umul_optab->handlers[(int) DImode].lib_call = "__umuldi3";
- umul_optab->handlers[(int) SFmode].lib_call = "__umulsf3";
- umul_optab->handlers[(int) DFmode].lib_call = "__umuldf3";
-
- #ifdef HAVE_umulqihi3
- if (HAVE_umulqihi3)
- umul_widen_optab->handlers[(int) HImode].insn_code = CODE_FOR_umulqihi3;
- #endif
- #ifdef HAVE_umulhisi3
- if (HAVE_umulhisi3)
- umul_widen_optab->handlers[(int) SImode].insn_code = CODE_FOR_umulhisi3;
- #endif
- #ifdef HAVE_umulsidi3
- if (HAVE_umulsidi3)
- umul_widen_optab->handlers[(int) DImode].insn_code = CODE_FOR_umulsidi3;
- #endif
-
- #ifdef HAVE_divqi3
- if (HAVE_divqi3)
- sdiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_divqi3;
- #endif
- #ifdef HAVE_divhi3
- if (HAVE_divhi3)
- sdiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_divhi3;
- #endif
- #ifdef HAVE_divsi3
- if (HAVE_divsi3)
- sdiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_divsi3;
- #endif
- #ifdef HAVE_divdi3
- if (HAVE_divdi3)
- sdiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_divdi3;
- #endif
-
- #ifdef DIVSI3_LIBCALL
- sdiv_optab->handlers[(int) SImode].lib_call = DIVSI3_LIBCALL;
- #else
- sdiv_optab->handlers[(int) SImode].lib_call = "__divsi3";
- #endif
- sdiv_optab->handlers[(int) DImode].lib_call = "__divdi3";
-
- #ifdef HAVE_udivqi3
- if (HAVE_udivqi3)
- udiv_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivqi3;
- #endif
- #ifdef HAVE_udivhi3
- if (HAVE_udivhi3)
- udiv_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivhi3;
- #endif
- #ifdef HAVE_udivsi3
- if (HAVE_udivsi3)
- udiv_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivsi3;
- #endif
- #ifdef HAVE_udivdi3
- if (HAVE_udivdi3)
- udiv_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivdi3;
- #endif
-
- #ifdef UDIVSI3_LIBCALL
- udiv_optab->handlers[(int) SImode].lib_call = UDIVSI3_LIBCALL;
- #else
- udiv_optab->handlers[(int) SImode].lib_call = "__udivsi3";
- #endif
- udiv_optab->handlers[(int) DImode].lib_call = "__udivdi3";
-
- #ifdef HAVE_divmodqi4
- if (HAVE_divmodqi4)
- sdivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_divmodqi4;
- #endif
- #ifdef HAVE_divmodhi4
- if (HAVE_divmodhi4)
- sdivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_divmodhi4;
- #endif
- #ifdef HAVE_divmodsi4
- if (HAVE_divmodsi4)
- sdivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_divmodsi4;
- #endif
- #ifdef HAVE_divmoddi4
- if (HAVE_divmoddi4)
- sdivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_divmoddi4;
- #endif
-
- #ifdef HAVE_udivmodqi4
- if (HAVE_udivmodqi4)
- udivmod_optab->handlers[(int) QImode].insn_code = CODE_FOR_udivmodqi4;
- #endif
- #ifdef HAVE_udivmodhi4
- if (HAVE_udivmodhi4)
- udivmod_optab->handlers[(int) HImode].insn_code = CODE_FOR_udivmodhi4;
- #endif
- #ifdef HAVE_udivmodsi4
- if (HAVE_udivmodsi4)
- udivmod_optab->handlers[(int) SImode].insn_code = CODE_FOR_udivmodsi4;
- #endif
- #ifdef HAVE_udivmoddi4
- if (HAVE_udivmoddi4)
- udivmod_optab->handlers[(int) DImode].insn_code = CODE_FOR_udivmoddi4;
- #endif
-
- #ifdef HAVE_modqi3
- if (HAVE_modqi3)
- smod_optab->handlers[(int) QImode].insn_code = CODE_FOR_modqi3;
- #endif
- #ifdef HAVE_modhi3
- if (HAVE_modhi3)
- smod_optab->handlers[(int) HImode].insn_code = CODE_FOR_modhi3;
- #endif
- #ifdef HAVE_modsi3
- if (HAVE_modsi3)
- smod_optab->handlers[(int) SImode].insn_code = CODE_FOR_modsi3;
- #endif
- #ifdef HAVE_moddi3
- if (HAVE_moddi3)
- smod_optab->handlers[(int) DImode].insn_code = CODE_FOR_moddi3;
- #endif
-
- #ifdef MODSI3_LIBCALL
- smod_optab->handlers[(int) SImode].lib_call = MODSI3_LIBCALL;
- #else
- smod_optab->handlers[(int) SImode].lib_call = "__modsi3";
- #endif
- smod_optab->handlers[(int) DImode].lib_call = "__moddi3";
-
- #ifdef HAVE_umodqi3
- if (HAVE_umodqi3)
- umod_optab->handlers[(int) QImode].insn_code = CODE_FOR_umodqi3;
- #endif
- #ifdef HAVE_umodhi3
- if (HAVE_umodhi3)
- umod_optab->handlers[(int) HImode].insn_code = CODE_FOR_umodhi3;
- #endif
- #ifdef HAVE_umodsi3
- if (HAVE_umodsi3)
- umod_optab->handlers[(int) SImode].insn_code = CODE_FOR_umodsi3;
- #endif
- #ifdef HAVE_umoddi3
- if (HAVE_umoddi3)
- umod_optab->handlers[(int) DImode].insn_code = CODE_FOR_umoddi3;
- #endif
-
- #ifdef UMODSI3_LIBCALL
- umod_optab->handlers[(int) SImode].lib_call = UMODSI3_LIBCALL;
- #else
- umod_optab->handlers[(int) SImode].lib_call = "__umodsi3";
- #endif
- umod_optab->handlers[(int) DImode].lib_call = "__umoddi3";
-
- #ifdef HAVE_divsf3
- if (HAVE_divsf3)
- flodiv_optab->handlers[(int) SFmode].insn_code = CODE_FOR_divsf3;
- #endif
- #ifdef HAVE_divdf3
- if (HAVE_divdf3)
- flodiv_optab->handlers[(int) DFmode].insn_code = CODE_FOR_divdf3;
- #endif
- flodiv_optab->handlers[(int) SFmode].lib_call = "__divsf3";
- flodiv_optab->handlers[(int) DFmode].lib_call = "__divdf3";
-
- #ifdef HAVE_ftruncsf2
- if (HAVE_ftruncsf2)
- ftrunc_optab->handlers[(int) SFmode].insn_code = CODE_FOR_ftruncsf2;
- #endif
- #ifdef HAVE_ftruncdf2
- if (HAVE_ftruncdf2)
- ftrunc_optab->handlers[(int) DFmode].insn_code = CODE_FOR_ftruncdf2;
- #endif
-
- #ifdef HAVE_andqi3
- if (HAVE_andqi3)
- and_optab->handlers[(int) QImode].insn_code = CODE_FOR_andqi3;
- #endif
- #ifdef HAVE_andhi3
- if (HAVE_andhi3)
- and_optab->handlers[(int) HImode].insn_code = CODE_FOR_andhi3;
- #endif
- #ifdef HAVE_andsi3
- if (HAVE_andsi3)
- and_optab->handlers[(int) SImode].insn_code = CODE_FOR_andsi3;
- #endif
- #ifdef HAVE_anddi3
- if (HAVE_anddi3)
- and_optab->handlers[(int) DImode].insn_code = CODE_FOR_anddi3;
- #endif
- and_optab->handlers[(int) DImode].lib_call = "__anddi3";
-
- #ifdef HAVE_andcbqi3
- if (HAVE_andcbqi3)
- andcb_optab->handlers[(int) QImode].insn_code = CODE_FOR_andcbqi3;
- #endif
- #ifdef HAVE_andcbhi3
- if (HAVE_andcbhi3)
- andcb_optab->handlers[(int) HImode].insn_code = CODE_FOR_andcbhi3;
- #endif
- #ifdef HAVE_andcbsi3
- if (HAVE_andcbsi3)
- andcb_optab->handlers[(int) SImode].insn_code = CODE_FOR_andcbsi3;
- #endif
- #ifdef HAVE_andcbdi3
- if (HAVE_andcbdi3)
- andcb_optab->handlers[(int) DImode].insn_code = CODE_FOR_andcbdi3;
- #endif
- andcb_optab->handlers[(int) DImode].lib_call = "__andcbdi3";
-
- #ifdef HAVE_iorqi3
- if (HAVE_iorqi3)
- ior_optab->handlers[(int) QImode].insn_code = CODE_FOR_iorqi3;
- #endif
- #ifdef HAVE_iorhi3
- if (HAVE_iorhi3)
- ior_optab->handlers[(int) HImode].insn_code = CODE_FOR_iorhi3;
- #endif
- #ifdef HAVE_iorsi3
- if (HAVE_iorsi3)
- ior_optab->handlers[(int) SImode].insn_code = CODE_FOR_iorsi3;
- #endif
- #ifdef HAVE_iordi3
- if (HAVE_iordi3)
- ior_optab->handlers[(int) DImode].insn_code = CODE_FOR_iordi3;
- #endif
- ior_optab->handlers[(int) DImode].lib_call = "__iordi3";
-
- #ifdef HAVE_xorqi3
- if (HAVE_xorqi3)
- xor_optab->handlers[(int) QImode].insn_code = CODE_FOR_xorqi3;
- #endif
- #ifdef HAVE_xorhi3
- if (HAVE_xorhi3)
- xor_optab->handlers[(int) HImode].insn_code = CODE_FOR_xorhi3;
- #endif
- #ifdef HAVE_xorsi3
- if (HAVE_xorsi3)
- xor_optab->handlers[(int) SImode].insn_code = CODE_FOR_xorsi3;
- #endif
- #ifdef HAVE_xordi3
- if (HAVE_xordi3)
- xor_optab->handlers[(int) DImode].insn_code = CODE_FOR_xordi3;
- #endif
- xor_optab->handlers[(int) DImode].lib_call = "__xordi3";
-
- #ifdef HAVE_ashlqi3
- if (HAVE_ashlqi3)
- ashl_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashlqi3;
- #endif
- #ifdef HAVE_ashlhi3
- if (HAVE_ashlhi3)
- ashl_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashlhi3;
- #endif
- #ifdef HAVE_ashlsi3
- if (HAVE_ashlsi3)
- ashl_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashlsi3;
- #endif
- #ifdef HAVE_ashldi3
- if (HAVE_ashldi3)
- ashl_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashldi3;
- #endif
- ashl_optab->handlers[(int) SImode].lib_call = "__ashlsi3";
- ashl_optab->handlers[(int) DImode].lib_call = "__ashldi3";
-
- #ifdef HAVE_ashrqi3
- if (HAVE_ashrqi3)
- ashr_optab->handlers[(int) QImode].insn_code = CODE_FOR_ashrqi3;
- #endif
- #ifdef HAVE_ashrhi3
- if (HAVE_ashrhi3)
- ashr_optab->handlers[(int) HImode].insn_code = CODE_FOR_ashrhi3;
- #endif
- #ifdef HAVE_ashrsi3
- if (HAVE_ashrsi3)
- ashr_optab->handlers[(int) SImode].insn_code = CODE_FOR_ashrsi3;
- #endif
- #ifdef HAVE_ashrdi3
- if (HAVE_ashrdi3)
- ashr_optab->handlers[(int) DImode].insn_code = CODE_FOR_ashrdi3;
- #endif
- ashr_optab->handlers[(int) SImode].lib_call = "__ashrsi3";
- ashr_optab->handlers[(int) DImode].lib_call = "__ashrdi3";
-
- #ifdef HAVE_lshlqi3
- if (HAVE_lshlqi3)
- lshl_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshlqi3;
- #endif
- #ifdef HAVE_lshlhi3
- if (HAVE_lshlhi3)
- lshl_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshlhi3;
- #endif
- #ifdef HAVE_lshlsi3
- if (HAVE_lshlsi3)
- lshl_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshlsi3;
- #endif
- #ifdef HAVE_lshldi3
- if (HAVE_lshldi3)
- lshl_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshldi3;
- #endif
- lshl_optab->handlers[(int) SImode].lib_call = "__lshlsi3";
- lshl_optab->handlers[(int) DImode].lib_call = "__lshldi3";
-
- #ifdef HAVE_lshrqi3
- if (HAVE_lshrqi3)
- lshr_optab->handlers[(int) QImode].insn_code = CODE_FOR_lshrqi3;
- #endif
- #ifdef HAVE_lshrhi3
- if (HAVE_lshrhi3)
- lshr_optab->handlers[(int) HImode].insn_code = CODE_FOR_lshrhi3;
- #endif
- #ifdef HAVE_lshrsi3
- if (HAVE_lshrsi3)
- lshr_optab->handlers[(int) SImode].insn_code = CODE_FOR_lshrsi3;
- #endif
- #ifdef HAVE_lshrdi3
- if (HAVE_lshrdi3)
- lshr_optab->handlers[(int) DImode].insn_code = CODE_FOR_lshrdi3;
- #endif
- lshr_optab->handlers[(int) SImode].lib_call = "__lshrsi3";
- lshr_optab->handlers[(int) DImode].lib_call = "__lshrdi3";
-
- #ifdef HAVE_rotlqi3
- if (HAVE_rotlqi3)
- rotl_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotlqi3;
- #endif
- #ifdef HAVE_rotlhi3
- if (HAVE_rotlhi3)
- rotl_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotlhi3;
- #endif
- #ifdef HAVE_rotlsi3
- if (HAVE_rotlsi3)
- rotl_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotlsi3;
- #endif
- #ifdef HAVE_rotldi3
- if (HAVE_rotldi3)
- rotl_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotldi3;
- #endif
- rotl_optab->handlers[(int) SImode].lib_call = "__rotlsi3";
- rotl_optab->handlers[(int) DImode].lib_call = "__rotldi3";
-
- #ifdef HAVE_rotrqi3
- if (HAVE_rotrqi3)
- rotr_optab->handlers[(int) QImode].insn_code = CODE_FOR_rotrqi3;
- #endif
- #ifdef HAVE_rotrhi3
- if (HAVE_rotrhi3)
- rotr_optab->handlers[(int) HImode].insn_code = CODE_FOR_rotrhi3;
- #endif
- #ifdef HAVE_rotrsi3
- if (HAVE_rotrsi3)
- rotr_optab->handlers[(int) SImode].insn_code = CODE_FOR_rotrsi3;
- #endif
- #ifdef HAVE_rotrdi3
- if (HAVE_rotrdi3)
- rotr_optab->handlers[(int) DImode].insn_code = CODE_FOR_rotrdi3;
- #endif
- rotr_optab->handlers[(int) SImode].lib_call = "__rotrsi3";
- rotr_optab->handlers[(int) DImode].lib_call = "__rotrdi3";
-
- #ifdef HAVE_negqi2
- if (HAVE_negqi2)
- neg_optab->handlers[(int) QImode].insn_code = CODE_FOR_negqi2;
- #endif
- #ifdef HAVE_neghi2
- if (HAVE_neghi2)
- neg_optab->handlers[(int) HImode].insn_code = CODE_FOR_neghi2;
- #endif
- #ifdef HAVE_negsi2
- if (HAVE_negsi2)
- neg_optab->handlers[(int) SImode].insn_code = CODE_FOR_negsi2;
- #endif
- #ifdef HAVE_negdi2
- if (HAVE_negdi2)
- neg_optab->handlers[(int) DImode].insn_code = CODE_FOR_negdi2;
- #endif
- #ifdef HAVE_negsf2
- if (HAVE_negsf2)
- neg_optab->handlers[(int) SFmode].insn_code = CODE_FOR_negsf2;
- #endif
- #ifdef HAVE_negdf2
- if (HAVE_negdf2)
- neg_optab->handlers[(int) DFmode].insn_code = CODE_FOR_negdf2;
- #endif
- neg_optab->handlers[(int) SImode].lib_call = "__negsi2";
- neg_optab->handlers[(int) DImode].lib_call = "__negdi2";
- neg_optab->handlers[(int) SFmode].lib_call = "__negsf2";
- neg_optab->handlers[(int) DFmode].lib_call = "__negdf2";
-
- #ifdef HAVE_absqi2
- if (HAVE_absqi2)
- abs_optab->handlers[(int) QImode].insn_code = CODE_FOR_absqi2;
- #endif
- #ifdef HAVE_abshi2
- if (HAVE_abshi2)
- abs_optab->handlers[(int) HImode].insn_code = CODE_FOR_abshi2;
- #endif
- #ifdef HAVE_abssi2
- if (HAVE_abssi2)
- abs_optab->handlers[(int) SImode].insn_code = CODE_FOR_abssi2;
- #endif
- #ifdef HAVE_absdi2
- if (HAVE_absdi2)
- abs_optab->handlers[(int) DImode].insn_code = CODE_FOR_absdi2;
- #endif
- #ifdef HAVE_abssf2
- if (HAVE_abssf2)
- abs_optab->handlers[(int) SFmode].insn_code = CODE_FOR_abssf2;
- #endif
- #ifdef HAVE_absdf2
- if (HAVE_absdf2)
- abs_optab->handlers[(int) DFmode].insn_code = CODE_FOR_absdf2;
- #endif
- /* No library calls here! If there is no abs instruction,
- expand_expr will generate a conditional negation. */
-
- #ifdef HAVE_one_cmplqi2
- if (HAVE_one_cmplqi2)
- one_cmpl_optab->handlers[(int) QImode].insn_code = CODE_FOR_one_cmplqi2;
- #endif
- #ifdef HAVE_one_cmplhi2
- if (HAVE_one_cmplhi2)
- one_cmpl_optab->handlers[(int) HImode].insn_code = CODE_FOR_one_cmplhi2;
- #endif
- #ifdef HAVE_one_cmplsi2
- if (HAVE_one_cmplsi2)
- one_cmpl_optab->handlers[(int) SImode].insn_code = CODE_FOR_one_cmplsi2;
- #endif
- #ifdef HAVE_one_cmpldi2
- if (HAVE_one_cmpldi2)
- one_cmpl_optab->handlers[(int) DImode].insn_code = CODE_FOR_one_cmpldi2;
- #endif
- one_cmpl_optab->handlers[(int) SImode].lib_call = "__one_cmplsi2";
- one_cmpl_optab->handlers[(int) DImode].lib_call = "__one_cmpldi2";
-
- #ifdef HAVE_ffsqi2
- if (HAVE_ffsqi2)
- ffs_optab->handlers[(int) QImode].insn_code = CODE_FOR_ffsqi2;
- #endif
- #ifdef HAVE_ffshi2
- if (HAVE_ffshi2)
- ffs_optab->handlers[(int) HImode].insn_code = CODE_FOR_ffshi2;
- #endif
- #ifdef HAVE_ffssi2
- if (HAVE_ffssi2)
- ffs_optab->handlers[(int) SImode].insn_code = CODE_FOR_ffssi2;
- #endif
- #ifdef HAVE_ffsdi2
- if (HAVE_ffsdi2)
- ffs_optab->handlers[(int) DImode].insn_code = CODE_FOR_ffsdi2;
- #endif
- ffs_optab->handlers[(int) SImode].lib_call = "ffs";
-
- #ifdef HAVE_movqi
- if (HAVE_movqi)
- mov_optab->handlers[(int) QImode].insn_code = CODE_FOR_movqi;
- #endif
- #ifdef HAVE_movhi
- if (HAVE_movhi)
- mov_optab->handlers[(int) HImode].insn_code = CODE_FOR_movhi;
- #endif
- #ifdef HAVE_movsi
- if (HAVE_movsi)
- mov_optab->handlers[(int) SImode].insn_code = CODE_FOR_movsi;
- #endif
- #ifdef HAVE_movdi
- if (HAVE_movdi)
- mov_optab->handlers[(int) DImode].insn_code = CODE_FOR_movdi;
- #endif
- #ifdef HAVE_movti
- if (HAVE_movti)
- mov_optab->handlers[(int) TImode].insn_code = CODE_FOR_movti;
- #endif
- #ifdef HAVE_movsf
- if (HAVE_movsf)
- mov_optab->handlers[(int) SFmode].insn_code = CODE_FOR_movsf;
- #endif
- #ifdef HAVE_movdf
- if (HAVE_movdf)
- mov_optab->handlers[(int) DFmode].insn_code = CODE_FOR_movdf;
- #endif
- #ifdef HAVE_movtf
- if (HAVE_movtf)
- mov_optab->handlers[(int) TFmode].insn_code = CODE_FOR_movtf;
- #endif
-
- #ifdef HAVE_movstrictqi
- if (HAVE_movstrictqi)
- movstrict_optab->handlers[(int) QImode].insn_code = CODE_FOR_movstrictqi;
- #endif
- #ifdef HAVE_movstricthi
- if (HAVE_movstricthi)
- movstrict_optab->handlers[(int) HImode].insn_code = CODE_FOR_movstricthi;
- #endif
- #ifdef HAVE_movstrictsi
- if (HAVE_movstrictsi)
- movstrict_optab->handlers[(int) SImode].insn_code = CODE_FOR_movstrictsi;
- #endif
- #ifdef HAVE_movstrictdi
- if (HAVE_movstrictdi)
- movstrict_optab->handlers[(int) DImode].insn_code = CODE_FOR_movstrictdi;
- #endif
-
- #ifdef HAVE_cmpqi
- if (HAVE_cmpqi)
- cmp_optab->handlers[(int) QImode].insn_code = CODE_FOR_cmpqi;
- #endif
- #ifdef HAVE_cmphi
- if (HAVE_cmphi)
- cmp_optab->handlers[(int) HImode].insn_code = CODE_FOR_cmphi;
- #endif
- #ifdef HAVE_cmpsi
- if (HAVE_cmpsi)
- cmp_optab->handlers[(int) SImode].insn_code = CODE_FOR_cmpsi;
- #endif
- #ifdef HAVE_cmpdi
- if (HAVE_cmpdi)
- cmp_optab->handlers[(int) DImode].insn_code = CODE_FOR_cmpdi;
- #endif
- #ifdef HAVE_cmpsf
- if (HAVE_cmpsf)
- cmp_optab->handlers[(int) SFmode].insn_code = CODE_FOR_cmpsf;
- #endif
- #ifdef HAVE_cmpdf
- if (HAVE_cmpdf)
- cmp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cmpdf;
- #endif
- #ifdef HAVE_tstqi
- if (HAVE_tstqi)
- tst_optab->handlers[(int) QImode].insn_code = CODE_FOR_tstqi;
- #endif
- #ifdef HAVE_tsthi
- if (HAVE_tsthi)
- tst_optab->handlers[(int) HImode].insn_code = CODE_FOR_tsthi;
- #endif
- #ifdef HAVE_tstsi
- if (HAVE_tstsi)
- tst_optab->handlers[(int) SImode].insn_code = CODE_FOR_tstsi;
- #endif
- #ifdef HAVE_tstdi
- if (HAVE_tstdi)
- tst_optab->handlers[(int) DImode].insn_code = CODE_FOR_tstdi;
- #endif
- #ifdef HAVE_tstsf
- if (HAVE_tstsf)
- tst_optab->handlers[(int) SFmode].insn_code = CODE_FOR_tstsf;
- #endif
- #ifdef HAVE_tstdf
- if (HAVE_tstdf)
- tst_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tstdf;
- #endif
- /* Comparison libcalls for integers MUST come in pairs, signed/unsigned. */
- cmp_optab->handlers[(int) DImode].lib_call = "__cmpdi2";
- ucmp_optab->handlers[(int) DImode].lib_call = "__ucmpdi2";
- cmp_optab->handlers[(int) SFmode].lib_call = "__cmpsf2";
- cmp_optab->handlers[(int) DFmode].lib_call = "__cmpdf2";
-
- #if HAVE_beq
- if (HAVE_beq)
- bcc_gen_fctn[(int) EQ] = gen_beq;
- #endif
- #if HAVE_bne
- if (HAVE_bne)
- bcc_gen_fctn[(int) NE] = gen_bne;
- #endif
- #if HAVE_bgt
- if (HAVE_bgt)
- bcc_gen_fctn[(int) GT] = gen_bgt;
- #endif
- #if HAVE_bge
- if (HAVE_bge)
- bcc_gen_fctn[(int) GE] = gen_bge;
- #endif
- #if HAVE_bgtu
- if (HAVE_bgtu)
- bcc_gen_fctn[(int) GTU] = gen_bgtu;
- #endif
- #if HAVE_bgeu
- if (HAVE_bgeu)
- bcc_gen_fctn[(int) GEU] = gen_bgeu;
- #endif
- #if HAVE_blt
- if (HAVE_blt)
- bcc_gen_fctn[(int) LT] = gen_blt;
- #endif
- #if HAVE_ble
- if (HAVE_ble)
- bcc_gen_fctn[(int) LE] = gen_ble;
- #endif
- #if HAVE_bltu
- if (HAVE_bltu)
- bcc_gen_fctn[(int) LTU] = gen_bltu;
- #endif
- #if HAVE_bleu
- if (HAVE_bleu)
- bcc_gen_fctn[(int) LEU] = gen_bleu;
- #endif
-
- #if HAVE_seq
- if (HAVE_seq)
- setcc_gen_fctn[(int) EQ] = gen_seq;
- #endif
- #if HAVE_sne
- if (HAVE_sne)
- setcc_gen_fctn[(int) NE] = gen_sne;
- #endif
- #if HAVE_sgt
- if (HAVE_sgt)
- setcc_gen_fctn[(int) GT] = gen_sgt;
- #endif
- #if HAVE_sge
- if (HAVE_sge)
- setcc_gen_fctn[(int) GE] = gen_sge;
- #endif
- #if HAVE_sgtu
- if (HAVE_sgtu)
- setcc_gen_fctn[(int) GTU] = gen_sgtu;
- #endif
- #if HAVE_sgeu
- if (HAVE_sgeu)
- setcc_gen_fctn[(int) GEU] = gen_sgeu;
- #endif
- #if HAVE_slt
- if (HAVE_slt)
- setcc_gen_fctn[(int) LT] = gen_slt;
- #endif
- #if HAVE_sle
- if (HAVE_sle)
- setcc_gen_fctn[(int) LE] = gen_sle;
- #endif
- #if HAVE_sltu
- if (HAVE_sltu)
- setcc_gen_fctn[(int) LTU] = gen_sltu;
- #endif
- #if HAVE_sleu
- if (HAVE_sleu)
- setcc_gen_fctn[(int) LEU] = gen_sleu;
- #endif
- }
-